--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
tools/colorgen.py a88b31d033010d3b7f3e73d8ebce0c4a6d6f6043 (a88b31d0) Text, 10.78 KB
T8b949e#!/usr/bin/env python3
T8b949e"""
Color Table Generator with Perceptual Normalization
Generates HSL color tables with optional normalization to uniform perceptual
intensity (CIELAB L*) followed by global lightness scaling.
"""
Tff7b72import T7ee787argparse
Tff7b72import T7ee787colorsys
Tff7b72import T7ee787math
Tff7b72import T7ee787sys
Tff7b72def Td2a8ffhsl_to_rgbTb4b4b4(Te6edf3hTb4b4b4, Te6edf3sTb4b4b4, Te6edf3lTb4b4b4)Tb4b4b4:
T8b949e"""Convert HSL (0-360, 0-100, 0-100) to RGB (0.0-1.0)."""
Te6edf3h_norm Tff7b72= Tb4b4b4(Te6edf3h Tff7b72% T79c0ff360Tb4b4b4) Tff7b72/ T79c0ff360.0
Te6edf3s_norm Tff7b72= Tffa657maxTb4b4b4(T79c0ff0Tb4b4b4, Tffa657minTb4b4b4(T79c0ff100Tb4b4b4, Te6edf3sTb4b4b4)Tb4b4b4) Tff7b72/ T79c0ff100.0
Te6edf3l_norm Tff7b72= Tffa657maxTb4b4b4(T79c0ff0Tb4b4b4, Tffa657minTb4b4b4(T79c0ff100Tb4b4b4, Te6edf3lTb4b4b4)Tb4b4b4) Tff7b72/ T79c0ff100.0
Te6edf3rTb4b4b4, Te6edf3gTb4b4b4, Te6edf3b Tff7b72= Te6edf3colorsysTff7b72.Td2a8ffhls_to_rgbTb4b4b4(Te6edf3h_normTb4b4b4, Te6edf3l_normTb4b4b4, Te6edf3s_normTb4b4b4)
Tff7b72return Tb4b4b4(Te6edf3rTb4b4b4, Te6edf3gTb4b4b4, Te6edf3bTb4b4b4)
Tff7b72def Td2a8ffrgb_to_hexTb4b4b4(Te6edf3rTb4b4b4, Te6edf3gTb4b4b4, Te6edf3bTb4b4b4)Tb4b4b4:
T8b949e"""Convert RGB 0.0-1.0 to lowercase hex string."""
Te6edf3r Tff7b72= Tffa657maxTb4b4b4(T79c0ff0Tb4b4b4, Tffa657minTb4b4b4(T79c0ff1Tb4b4b4, Te6edf3rTb4b4b4)Tb4b4b4)
Te6edf3g Tff7b72= Tffa657maxTb4b4b4(T79c0ff0Tb4b4b4, Tffa657minTb4b4b4(T79c0ff1Tb4b4b4, Te6edf3gTb4b4b4)Tb4b4b4)
Te6edf3b Tff7b72= Tffa657maxTb4b4b4(T79c0ff0Tb4b4b4, Tffa657minTb4b4b4(T79c0ff1Tb4b4b4, Te6edf3bTb4b4b4)Tb4b4b4)
Tff7b72return Ta5d6fffTa5d6ff"Tffd700{Tffa657intTb4b4b4(Te6edf3rTff7b72*T79c0ff255Tb4b4b4)Tffd700:Ta5d6ff02xTffd700}Tffd700{Tffa657intTb4b4b4(Te6edf3gTff7b72*T79c0ff255Tb4b4b4)Tffd700:Ta5d6ff02xTffd700}Tffd700{Tffa657intTb4b4b4(Te6edf3bTff7b72*T79c0ff255Tb4b4b4)Tffd700:Ta5d6ff02xTffd700}Ta5d6ff"
T8b949e# CIELAB conversion functions
Tff7b72def Td2a8ffsrgb_to_linearTb4b4b4(Te6edf3cTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3c Tff7b72<Tff7b72= T79c0ff0.04045Tb4b4b4:
Tff7b72return Te6edf3c Tff7b72/ T79c0ff12.92
Tff7b72return Tb4b4b4(Tb4b4b4(Te6edf3c Tff7b72+ T79c0ff0.055Tb4b4b4) Tff7b72/ T79c0ff1.055Tb4b4b4) Tff7b72*Tff7b72* T79c0ff2.4
Tff7b72def Td2a8fflinear_to_srgbTb4b4b4(Te6edf3cTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3c Tff7b72<Tff7b72= T79c0ff0.0031308Tb4b4b4:
Tff7b72return Te6edf3c Tff7b72* T79c0ff12.92
Tff7b72return T79c0ff1.055 Tff7b72* Tb4b4b4(Te6edf3c Tff7b72*Tff7b72* Tb4b4b4(T79c0ff1Tff7b72/T79c0ff2.4Tb4b4b4)Tb4b4b4) Tff7b72- T79c0ff0.055
Tff7b72def Td2a8ffrgb_to_labTb4b4b4(Te6edf3rTb4b4b4, Te6edf3gTb4b4b4, Te6edf3bTb4b4b4)Tb4b4b4:
T8b949e"""Convert sRGB (0-1) to CIELAB (L: 0-100, a,b: ~-128 to 127). D65 illuminant."""
T8b949e# sRGB to Linear
Te6edf3r_lin Tff7b72= Te6edf3srgb_to_linearTb4b4b4(Te6edf3rTb4b4b4)
Te6edf3g_lin Tff7b72= Te6edf3srgb_to_linearTb4b4b4(Te6edf3gTb4b4b4)
Te6edf3b_lin Tff7b72= Te6edf3srgb_to_linearTb4b4b4(Te6edf3bTb4b4b4)
T8b949e# Linear to XYZ (D65)
Te6edf3X Tff7b72= T79c0ff0.4124564 Tff7b72* Te6edf3r_lin Tff7b72+ T79c0ff0.3575761 Tff7b72* Te6edf3g_lin Tff7b72+ T79c0ff0.1804375 Tff7b72* Te6edf3b_lin
Te6edf3Y Tff7b72= T79c0ff0.2126729 Tff7b72* Te6edf3r_lin Tff7b72+ T79c0ff0.7151522 Tff7b72* Te6edf3g_lin Tff7b72+ T79c0ff0.0721750 Tff7b72* Te6edf3b_lin
Te6edf3Z Tff7b72= T79c0ff0.0193339 Tff7b72* Te6edf3r_lin Tff7b72+ T79c0ff0.1191920 Tff7b72* Te6edf3g_lin Tff7b72+ T79c0ff0.9503041 Tff7b72* Te6edf3b_lin
T8b949e# XYZ to LAB
Te6edf3XnTb4b4b4, Te6edf3YnTb4b4b4, Te6edf3Zn Tff7b72= T79c0ff95.047Tb4b4b4, T79c0ff100.0Tb4b4b4, T79c0ff108.883
Te6edf3delta Tff7b72= T79c0ff6Tff7b72/T79c0ff29
Tff7b72def Td2a8fffTb4b4b4(Te6edf3tTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3t Tff7b72> Te6edf3deltaTff7b72*Tff7b72*T79c0ff3Tb4b4b4:
Tff7b72return Te6edf3t Tff7b72*Tff7b72* Tb4b4b4(T79c0ff1Tff7b72/T79c0ff3Tb4b4b4)
Tff7b72return Te6edf3t Tff7b72/ Tb4b4b4(T79c0ff3 Tff7b72* Te6edf3deltaTff7b72*Tff7b72*T79c0ff2Tb4b4b4) Tff7b72+ T79c0ff4Tff7b72/T79c0ff29
Te6edf3L Tff7b72= T79c0ff116 Tff7b72* Te6edf3fTb4b4b4(Te6edf3Y Tff7b72/ Te6edf3YnTb4b4b4) Tff7b72- T79c0ff16
Te6edf3a Tff7b72= T79c0ff500 Tff7b72* Tb4b4b4(Te6edf3fTb4b4b4(Te6edf3X Tff7b72/ Te6edf3XnTb4b4b4) Tff7b72- Te6edf3fTb4b4b4(Te6edf3Y Tff7b72/ Te6edf3YnTb4b4b4)Tb4b4b4)
Te6edf3b_val Tff7b72= T79c0ff200 Tff7b72* Tb4b4b4(Te6edf3fTb4b4b4(Te6edf3Y Tff7b72/ Te6edf3YnTb4b4b4) Tff7b72- Te6edf3fTb4b4b4(Te6edf3Z Tff7b72/ Te6edf3ZnTb4b4b4)Tb4b4b4)
Tff7b72return Tb4b4b4(Te6edf3LTb4b4b4, Te6edf3aTb4b4b4, Te6edf3b_valTb4b4b4)
Tff7b72def Td2a8fflab_to_rgbTb4b4b4(Te6edf3LTb4b4b4, Te6edf3aTb4b4b4, Te6edf3b_valTb4b4b4)Tb4b4b4:
T8b949e"""Convert CIELAB to sRGB (0-1)."""
Te6edf3XnTb4b4b4, Te6edf3YnTb4b4b4, Te6edf3Zn Tff7b72= T79c0ff95.047Tb4b4b4, T79c0ff100.0Tb4b4b4, T79c0ff108.883
Te6edf3delta Tff7b72= T79c0ff6Tff7b72/T79c0ff29
Tff7b72def Td2a8ffinv_fTb4b4b4(Te6edf3yTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3y Tff7b72> Te6edf3deltaTb4b4b4:
Tff7b72return Te6edf3y Tff7b72*Tff7b72* T79c0ff3
Tff7b72return T79c0ff3 Tff7b72* Te6edf3deltaTff7b72*Tff7b72*T79c0ff2 Tff7b72* Tb4b4b4(Te6edf3y Tff7b72- T79c0ff4Tff7b72/T79c0ff29Tb4b4b4)
Te6edf3L_adj Tff7b72= Tb4b4b4(Te6edf3L Tff7b72+ T79c0ff16Tb4b4b4) Tff7b72/ T79c0ff116
Te6edf3X Tff7b72= Te6edf3Xn Tff7b72* Te6edf3inv_fTb4b4b4(Te6edf3L_adj Tff7b72+ Te6edf3a Tff7b72/ T79c0ff500Tb4b4b4)
Te6edf3Y Tff7b72= Te6edf3Yn Tff7b72* Te6edf3inv_fTb4b4b4(Te6edf3L_adjTb4b4b4)
Te6edf3Z Tff7b72= Te6edf3Zn Tff7b72* Te6edf3inv_fTb4b4b4(Te6edf3L_adj Tff7b72- Te6edf3b_val Tff7b72/ T79c0ff200Tb4b4b4)
T8b949e# XYZ to Linear RGB
Te6edf3r_lin Tff7b72= T79c0ff3.2404542 Tff7b72* Te6edf3X Tff7b72- T79c0ff1.5371385 Tff7b72* Te6edf3Y Tff7b72- T79c0ff0.4985314 Tff7b72* Te6edf3Z
Te6edf3g_lin Tff7b72= Tff7b72-T79c0ff0.9692660 Tff7b72* Te6edf3X Tff7b72+ T79c0ff1.8760108 Tff7b72* Te6edf3Y Tff7b72+ T79c0ff0.0415560 Tff7b72* Te6edf3Z
Te6edf3b_lin Tff7b72= T79c0ff0.0556434 Tff7b72* Te6edf3X Tff7b72- T79c0ff0.2040259 Tff7b72* Te6edf3Y Tff7b72+ T79c0ff1.0572252 Tff7b72* Te6edf3Z
Te6edf3r Tff7b72= Te6edf3linear_to_srgbTb4b4b4(Te6edf3r_linTb4b4b4)
Te6edf3g Tff7b72= Te6edf3linear_to_srgbTb4b4b4(Te6edf3g_linTb4b4b4)
Te6edf3b Tff7b72= Te6edf3linear_to_srgbTb4b4b4(Te6edf3b_linTb4b4b4)
Tff7b72return Tb4b4b4(Te6edf3rTb4b4b4, Te6edf3gTb4b4b4, Te6edf3bTb4b4b4)
Tff7b72def Td2a8ffgenerate_colorsTb4b4b4(
Te6edf3huesTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3hue_startTff7b72=T79c0ff0.0Tb4b4b4,
Te6edf3hue_stepTff7b72=T79c0ff30.0Tb4b4b4,
Te6edf3sat_startTff7b72=T79c0ff70.0Tb4b4b4,
Te6edf3sat_stepTff7b72=T79c0ff0.0Tb4b4b4,
Te6edf3sat_stepsTff7b72=T79c0ff1Tb4b4b4,
Te6edf3light_startTff7b72=T79c0ff50.0Tb4b4b4,
Te6edf3light_stepTff7b72=T79c0ff0.0Tb4b4b4,
Te6edf3light_stepsTff7b72=T79c0ff1Tb4b4b4,
Te6edf3perceptual_multiplierTff7b72=T79c0ff1.0Tb4b4b4,
Te6edf3use_hsl_spaceTff7b72=Tff7b72FalseTb4b4b4,
Te6edf3normalizeTff7b72=Tff7b72FalseTb4b4b4,
Te6edf3normalize_targetTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3discardsTff7b72=Tb4b4b4[Tb4b4b4]
Tb4b4b4)Tb4b4b4:
T8b949e"""
Generate color table with optional perceptual normalization.
Pipeline:
1. Generate HSL variations
2. If normalize: Convert to LAB, set all L* to target (mean or specified)
3. Apply global perceptual multiplier to L*
4. Convert to RGB and output hex
"""
T8b949e# Determine hue list
Tff7b72if Te6edf3hues Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3hue_list Tff7b72= Tb4b4b4[Tffa657floatTb4b4b4(Te6edf3hTb4b4b4) Tff7b72% T79c0ff360 Tff7b72for Te6edf3h Tff7b72in Te6edf3huesTb4b4b4]
Tff7b72elseTb4b4b4:
Te6edf3hue_list Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3current Tff7b72= Te6edf3hue_start Tff7b72% T79c0ff360
Tff7b72if Te6edf3hue_step Tff7b72<Tff7b72= T79c0ff0Tb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffhue_step must be positive when using start/step modeTa5d6ff"Tb4b4b4)
Tff7b72while Te6edf3current Tff7b72< T79c0ff360Tb4b4b4:
Te6edf3hue_listTff7b72.Td2a8ffappendTb4b4b4(Te6edf3currentTb4b4b4)
Te6edf3current Tff7b72+Tff7b72= Te6edf3hue_step
T8b949e# Determine if we need LAB processing
Te6edf3needs_lab Tff7b72= Te6edf3normalize Tff7b72or Tb4b4b4(Te6edf3perceptual_multiplier Tff7b72!= T79c0ff1.0Tb4b4b4) Tff7b72or Tff7b72not Te6edf3use_hsl_space
Te6edf3colors Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3lab_colors Tff7b72= Tb4b4b4[Tb4b4b4] T8b949e# Store as (L, a, b) tuples if processing needed
Tff7b72for Te6edf3h Tff7b72in Te6edf3hue_listTb4b4b4:
Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(Te6edf3sat_stepsTb4b4b4)Tb4b4b4:
Te6edf3s Tff7b72= Te6edf3sat_start Tff7b72+ Tb4b4b4(Te6edf3i Tff7b72* Te6edf3sat_stepTb4b4b4)
Te6edf3s Tff7b72= Tffa657maxTb4b4b4(T79c0ff0Tb4b4b4, Tffa657minTb4b4b4(T79c0ff100Tb4b4b4, Te6edf3sTb4b4b4)Tb4b4b4)
Tff7b72for Te6edf3j Tff7b72in Tffa657rangeTb4b4b4(Te6edf3light_stepsTb4b4b4)Tb4b4b4:
T8b949e# l = light_start + (j * light_step)
Te6edf3l Tff7b72= Te6edf3light_start Tff7b72+ Tb4b4b4(Te6edf3i Tff7b72* Te6edf3light_stepTb4b4b4)
Te6edf3l Tff7b72= Tffa657maxTb4b4b4(T79c0ff0Tb4b4b4, Tffa657minTb4b4b4(T79c0ff100Tb4b4b4, Te6edf3lTb4b4b4)Tb4b4b4)
Te6edf3rTb4b4b4, Te6edf3gTb4b4b4, Te6edf3b Tff7b72= Te6edf3hsl_to_rgbTb4b4b4(Te6edf3hTb4b4b4, Te6edf3sTb4b4b4, Te6edf3lTb4b4b4)
Tff7b72if Tff7b72not Te6edf3needs_labTb4b4b4:
Te6edf3colorsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3rgb_to_hexTb4b4b4(Te6edf3rTb4b4b4, Te6edf3gTb4b4b4, Te6edf3bTb4b4b4)Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3LTb4b4b4, Te6edf3aTb4b4b4, Te6edf3b_lab Tff7b72= Te6edf3rgb_to_labTb4b4b4(Te6edf3rTb4b4b4, Te6edf3gTb4b4b4, Te6edf3bTb4b4b4)
Te6edf3lab_colorsTff7b72.Td2a8ffappendTb4b4b4(Tb4b4b4(Te6edf3LTb4b4b4, Te6edf3aTb4b4b4, Te6edf3b_labTb4b4b4)Tb4b4b4)
Te6edf3filtered_colors Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3filtered_lab_colors Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3i Tff7b72= T79c0ff0
Tff7b72for Te6edf3c Tff7b72in Te6edf3colorsTb4b4b4:
Te6edf3i Tff7b72+Tff7b72= T79c0ff1
Tff7b72if Tff7b72not Tffa657strTb4b4b4(Te6edf3iTb4b4b4) Tff7b72in Te6edf3discardsTb4b4b4:
Te6edf3filtered_colorsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3cTb4b4b4)
Te6edf3i Tff7b72= T79c0ff0
Tff7b72for Te6edf3c Tff7b72in Te6edf3lab_colorsTb4b4b4:
Te6edf3i Tff7b72+Tff7b72= T79c0ff1
Tff7b72if Tff7b72not Tffa657strTb4b4b4(Te6edf3iTb4b4b4) Tff7b72in Te6edf3discardsTb4b4b4:
Te6edf3filtered_lab_colorsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3cTb4b4b4)
Te6edf3colors Tff7b72= Te6edf3filtered_colors
Te6edf3lab_colors Tff7b72= Te6edf3filtered_lab_colors
Tff7b72if Tff7b72not Te6edf3needs_labTb4b4b4:
Tff7b72return Te6edf3colors
T8b949e# Step 2: Perceptual Normalization (equalize intensity)
Tff7b72if Te6edf3normalizeTb4b4b4:
Tff7b72if Te6edf3normalize_target Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3target_L Tff7b72= Te6edf3normalize_target
Tff7b72elseTb4b4b4:
T8b949e# Calculate mean perceptual lightness
Te6edf3target_L Tff7b72= Tffa657sumTb4b4b4(Te6edf3labTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72for Te6edf3lab Tff7b72in Te6edf3lab_colorsTb4b4b4) Tff7b72/ Tffa657lenTb4b4b4(Te6edf3lab_colorsTb4b4b4)
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffTarget L*: Tffd700{Te6edf3target_LTffd700}Ta5d6ff"Tb4b4b4)
T8b949e# Clamp target to valid LAB range
Te6edf3target_L Tff7b72= Tffa657maxTb4b4b4(T79c0ff0Tb4b4b4, Tffa657minTb4b4b4(T79c0ff100Tb4b4b4, Te6edf3target_LTb4b4b4)Tb4b4b4)
T8b949e# Normalize all colors to target L, preserving hue (a, b)
Te6edf3lab_colors Tff7b72= Tb4b4b4[Tb4b4b4(Te6edf3target_LTb4b4b4, Te6edf3aTb4b4b4, Te6edf3bTb4b4b4) Tff7b72for Tb4b4b4(Te6edf3LTb4b4b4, Te6edf3aTb4b4b4, Te6edf3bTb4b4b4) Tff7b72in Te6edf3lab_colorsTb4b4b4]
T8b949e# Step 3: Apply final global perceptual multiplier
Te6edf3final_colors Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3LTb4b4b4, Te6edf3aTb4b4b4, Te6edf3b Tff7b72in Te6edf3lab_colorsTb4b4b4:
Te6edf3L_final Tff7b72= Te6edf3L Tff7b72* Te6edf3perceptual_multiplier
Te6edf3L_final Tff7b72= Tffa657maxTb4b4b4(T79c0ff0Tb4b4b4, Tffa657minTb4b4b4(T79c0ff100Tb4b4b4, Te6edf3L_finalTb4b4b4)Tb4b4b4)
Te6edf3rTb4b4b4, Te6edf3gTb4b4b4, Te6edf3b Tff7b72= Te6edf3lab_to_rgbTb4b4b4(Te6edf3L_finalTb4b4b4, Te6edf3aTb4b4b4, Te6edf3bTb4b4b4)
Te6edf3final_colorsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3rgb_to_hexTb4b4b4(Te6edf3rTb4b4b4, Te6edf3gTb4b4b4, Te6edf3bTb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3final_colors
Tff7b72def Td2a8ffmainTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3parser Tff7b72= Te6edf3argparseTff7b72.Td2a8ffArgumentParserTb4b4b4(
Te6edf3descriptionTff7b72=Ta5d6ff"Ta5d6ffGenerate perceptually normalized color tablesTa5d6ff"Tb4b4b4,
Te6edf3formatter_classTff7b72=Te6edf3argparseTff7b72.Td2a8ffRawDescriptionHelpFormatterTb4b4b4,
Te6edf3epilogTff7b72=Ta5d6ff"""
Ta5d6ffPipeline: HSL Generation → [Normalize to uniform L*] → Global Multiplier → Hex
Ta5d6ffExamples:
Ta5d6ff # 32 colors normalized to same perceptual intensity, then darkened 20Ta5d6ff%
Ta5d6ff python3 colorgen.py --hue-start 0 --hue-step 11.25 --sat-start 75 --normalize --perceptual-multiplier 0.8
Ta5d6ff
Ta5d6ff # Force all colors to exactly L*=55, then scale by 1.1
Ta5d6ff python3 colorgen.py --hues Ta5d6ff"Ta5d6ff0,90,180,270Ta5d6ff"Ta5d6ff --normalize --normalize-target 55 --perceptual-multiplier 1.1
Ta5d6ff
Ta5d6ff # Generate with lightness variation, normalize to mean intensity, output brightened
Ta5d6ff python3 colorgen.py --hue-start 15 --hue-step 30 --light-start 40 --light-step 10 --light-steps 3 --normalize --perceptual-multiplier 1.2
Ta5d6ff Ta5d6ff"""
Tb4b4b4)
T8b949e# Hue configuration
Te6edf3hue_group Tff7b72= Te6edf3parserTff7b72.Td2a8ffadd_mutually_exclusive_groupTb4b4b4(Tb4b4b4)
Te6edf3hue_groupTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--huesTa5d6ff"Tb4b4b4, Tffa657typeTff7b72=Tffa657strTb4b4b4, Te6edf3metavarTff7b72=Ta5d6ff"Ta5d6ffLISTTa5d6ff"Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffComma-separated hue values, e.g., Ta5d6ff"Ta5d6ff0,60,120Ta5d6ff"Ta5d6ff'Tb4b4b4)
Te6edf3hue_groupTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--hue-startTa5d6ff"Tb4b4b4, Tffa657typeTff7b72=Tffa657floatTb4b4b4, Te6edf3defaultTff7b72=T79c0ff0.0Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffInitial hue offset in degreesTa5d6ff"Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--hue-stepTa5d6ff"Tb4b4b4, Tffa657typeTff7b72=Tffa657floatTb4b4b4, Te6edf3defaultTff7b72=T79c0ff30.0Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffSeparation between huesTa5d6ff"Tb4b4b4)
T8b949e# Saturation/Lightness configuration
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--sat-startTa5d6ff"Tb4b4b4, Tffa657typeTff7b72=Tffa657floatTb4b4b4, Te6edf3defaultTff7b72=T79c0ff75.0Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffInitial saturation (0-100)Ta5d6ff"Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--sat-stepTa5d6ff"Tb4b4b4, Tffa657typeTff7b72=Tffa657floatTb4b4b4, Te6edf3defaultTff7b72=T79c0ff0.0Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffSaturation stepTa5d6ff"Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--sat-stepsTa5d6ff"Tb4b4b4, Tffa657typeTff7b72=Tffa657intTb4b4b4, Te6edf3defaultTff7b72=T79c0ff1Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffNumber of saturation variationsTa5d6ff"Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--light-startTa5d6ff"Tb4b4b4, Tffa657typeTff7b72=Tffa657floatTb4b4b4, Te6edf3defaultTff7b72=T79c0ff50.0Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffInitial lightness (0-100)Ta5d6ff"Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--light-stepTa5d6ff"Tb4b4b4, Tffa657typeTff7b72=Tffa657floatTb4b4b4, Te6edf3defaultTff7b72=T79c0ff0.0Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffLightness stepTa5d6ff"Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--light-stepsTa5d6ff"Tb4b4b4, Tffa657typeTff7b72=Tffa657intTb4b4b4, Te6edf3defaultTff7b72=T79c0ff1Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffNumber of lightness variationsTa5d6ff"Tb4b4b4)
T8b949e# Perceptual processing
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--normalizeTa5d6ff"Tb4b4b4, Te6edf3actionTff7b72=Ta5d6ff"Ta5d6ffstore_trueTa5d6ff"Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffNormalize all colors to same perceptual intensity (L*) before applying multiplierTa5d6ff"Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--normalize-targetTa5d6ff"Tb4b4b4, Tffa657typeTff7b72=Tffa657floatTb4b4b4, Te6edf3defaultTff7b72=Tff7b72NoneTb4b4b4, Te6edf3metavarTff7b72=Ta5d6ff"Ta5d6ffLTa5d6ff"Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffTarget L* value (0-100) for normalization. Default: mean of generated colorsTa5d6ff"Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--perceptual-multiplierTa5d6ff"Tb4b4b4, Tffa657typeTff7b72=Tffa657floatTb4b4b4, Te6edf3defaultTff7b72=T79c0ff1.0Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffFinal global lightness multiplier (1.0=no change)Ta5d6ff"Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--hsl-spaceTa5d6ff"Tb4b4b4, Te6edf3actionTff7b72=Ta5d6ff"Ta5d6ffstore_trueTa5d6ff"Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffSkip LAB conversion if not normalizing (faster, less accurate perceptually)Ta5d6ff"Tb4b4b4)
T8b949e# Output
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--python-listTa5d6ff"Tb4b4b4, Te6edf3actionTff7b72=Ta5d6ff"Ta5d6ffstore_trueTa5d6ff"Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffOutput as Python listTa5d6ff"Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--separatorTa5d6ff"Tb4b4b4, Tffa657typeTff7b72=Tffa657strTb4b4b4, Te6edf3defaultTff7b72=Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffSeparator between colorsTa5d6ff"Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--statsTa5d6ff"Tb4b4b4, Te6edf3actionTff7b72=Ta5d6ff"Ta5d6ffstore_trueTa5d6ff"Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffPrint generation stats to stderrTa5d6ff"Tb4b4b4)
Te6edf3hue_groupTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--discardTa5d6ff"Tb4b4b4, Tffa657typeTff7b72=Tffa657strTb4b4b4, Te6edf3metavarTff7b72=Ta5d6ff"Ta5d6ffLISTTa5d6ff"Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff'Ta5d6ffDiscard output indexes, e.g., Ta5d6ff"Ta5d6ff20,2,33Ta5d6ff"Ta5d6ff'Tb4b4b4)
Te6edf3args Tff7b72= Te6edf3parserTff7b72.Td2a8ffparse_argsTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3argsTff7b72.Td2a8ffhsl_space Tff7b72and Te6edf3argsTff7b72.Td2a8ffnormalizeTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffWarning: --hsl-space ignored because --normalize requires LAB spaceTa5d6ff"Tb4b4b4, Te6edf3fileTff7b72=Te6edf3sysTff7b72.Td2a8ffstderrTb4b4b4)
Te6edf3argsTff7b72.Td2a8ffhsl_space Tff7b72= Tff7b72False
Tff7b72tryTb4b4b4:
Tff7b72if Te6edf3argsTff7b72.Td2a8ffdiscardTb4b4b4: Te6edf3discards Tff7b72= Te6edf3argsTff7b72.Td2a8ffdiscardTff7b72.Td2a8ffsplitTb4b4b4(Ta5d6ff"Ta5d6ff,Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4: Te6edf3discards Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3colors Tff7b72= Te6edf3generate_colorsTb4b4b4(
Te6edf3huesTff7b72=Te6edf3argsTff7b72.Td2a8ffhuesTff7b72.Td2a8ffsplitTb4b4b4(Ta5d6ff"Ta5d6ff,Ta5d6ff"Tb4b4b4) Tff7b72if Te6edf3argsTff7b72.Td2a8ffhues Tff7b72else Tff7b72NoneTb4b4b4,
Te6edf3hue_startTff7b72=Te6edf3argsTff7b72.Td2a8ffhue_startTb4b4b4,
Te6edf3hue_stepTff7b72=Te6edf3argsTff7b72.Td2a8ffhue_stepTb4b4b4,
Te6edf3sat_startTff7b72=Te6edf3argsTff7b72.Td2a8ffsat_startTb4b4b4,
Te6edf3sat_stepTff7b72=Te6edf3argsTff7b72.Td2a8ffsat_stepTb4b4b4,
Te6edf3sat_stepsTff7b72=Te6edf3argsTff7b72.Td2a8ffsat_stepsTb4b4b4,
Te6edf3light_startTff7b72=Te6edf3argsTff7b72.Td2a8fflight_startTb4b4b4,
Te6edf3light_stepTff7b72=Te6edf3argsTff7b72.Td2a8fflight_stepTb4b4b4,
Te6edf3light_stepsTff7b72=Te6edf3argsTff7b72.Td2a8fflight_stepsTb4b4b4,
Te6edf3perceptual_multiplierTff7b72=Te6edf3argsTff7b72.Td2a8ffperceptual_multiplierTb4b4b4,
Te6edf3use_hsl_spaceTff7b72=Te6edf3argsTff7b72.Td2a8ffhsl_spaceTb4b4b4,
Te6edf3normalizeTff7b72=Te6edf3argsTff7b72.Td2a8ffnormalizeTb4b4b4,
Te6edf3normalize_targetTff7b72=Te6edf3argsTff7b72.Td2a8ffnormalize_targetTb4b4b4,
Te6edf3discardsTff7b72=Te6edf3discardsTb4b4b4,
Tb4b4b4)
Te6edf3i Tff7b72= T79c0ff0
T8b949e# Enable to test on light background
T8b949e# print(f"#!bg=fff\n")
Tff7b72if Te6edf3argsTff7b72.Td2a8ffpython_listTb4b4b4: Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffcolors = [Ta5d6ff"Tb4b4b4, Te6edf3endTff7b72=Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tff7b72for Te6edf3c Tff7b72in Te6edf3colorsTb4b4b4:
Te6edf3iTff7b72+Tff7b72=T79c0ff1
Tff7b72if Te6edf3argsTff7b72.Td2a8ffpython_listTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Tffea00\"Tffd700{Te6edf3cTffd700}Tffea00\"Ta5d6ff, Ta5d6ff"Tb4b4b4, Te6edf3endTff7b72=Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4: Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff`FTTffd700{Te6edf3cTffd700}Ta5d6ffcolored Tffd700{Te6edf3iTffd700}Ta5d6ff`fTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3argsTff7b72.Td2a8ffpython_listTb4b4b4: Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ff]Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3argsTff7b72.Td2a8ffstatsTb4b4b4:
Te6edf3total Tff7b72= Tffa657lenTb4b4b4(Te6edf3colorsTb4b4b4)
Te6edf3mode Tff7b72= Ta5d6ff"Ta5d6ffnormalized + Ta5d6ff" Tff7b72if Te6edf3argsTff7b72.Td2a8ffnormalize Tff7b72else Ta5d6ff"Ta5d6ff"
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff# Generated Tffd700{Te6edf3totalTffd700}Ta5d6ff colors (Tffd700{Te6edf3modeTffd700}Ta5d6ffL* × Tffd700{Te6edf3argsTff7b72.Td2a8ffperceptual_multiplierTffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4,
Te6edf3fileTff7b72=Te6edf3sysTff7b72.Td2a8ffstderrTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffError: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4, Te6edf3fileTff7b72=Te6edf3sysTff7b72.Td2a8ffstderrTb4b4b4)
Te6edf3sysTff7b72.Td2a8ffexitTb4b4b4(T79c0ff1Tb4b4b4)
Tff7b72if Tff7b72__name__ Tff7b72== Ta5d6ff"Ta5d6ff__main__Ta5d6ff"Tb4b4b4:
Te6edf3mainTb4b4b4(Tb4b4b4)
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────